import os
from asyncio import sleep

from fastapi import FastAPI, File, Form, HTTPException, UploadFile, status
from fastapi.responses import FileResponse

from .utils.calculate import calculate_file, doc_to_pdf

app = FastAPI(title='Printles-Calculator')

@app.get('/')
async def test():
    return 'Hello World'

@app.post('/calculate')
async def calculate(
    file: UploadFile=File(),        
    from_page: int | None=Form(default=None, description='文件打印起始页'),
    to_page: int | None=Form(default=None, description='文件打印结束页')):

    if (from_page is None and to_page is not None) \
    or (from_page is not None and to_page is None):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail='Format failed.'
        )
    
    filename = file.filename
    file_path = os.path.join(os.getcwd(), 'files', filename)

    ext = file.filename.rsplit('.', 1)[-1]
    if ext not in ['doc', 'docx', 'ppt', 'pptx', 'pdf']:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail='Unsupported file extension.'
        )
    
    try:
        with open(file_path, 'wb') as f:
            f.write(await file.read())

        if ext in ['doc', 'docx', 'ppt', 'pptx']:
            code = await doc_to_pdf(file_path)
            if code:
                raise Exception
            await sleep(0.1)

        page_color_list = await calculate_file(file_path=file_path.rsplit('.', 1)[0] + '.pdf')

        from_page = int(from_page) if int(from_page) >= 0 else 0
        to_page = to_page if int(to_page) <= len(page_color_list) else len(page_color_list)
        page_color_list = page_color_list[ from_page : to_page ]

        os.remove(file_path.rsplit('.', 1)[0] + '.pdf')
        color_pages = page_color_list.count(True)
        black_pages = len(page_color_list) - color_pages

        return {
            'code': 0,
            'message': 'success',
            'blackpages': black_pages,
            'colorpages': color_pages,
        }

    except Exception as e:
        with open(os.path.join(os.getcwd(), 'file_error.log'), 'w+', encoding='utf8') as file_error:
            file_error.writelines([e.__str__(), filename])

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=e.__str__() + filename
        )

@app.post('/convert', response_class=FileResponse)
async def convert_to_pdf(file: UploadFile=File()):
    filename = file.filename
    ext = filename.rsplit('.', 1)[-1]
    name = filename.rsplit('.', 1)[0]
    if ext not in ['doc', 'docx', 'ppt', 'pptx']:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail='Format failed.'
        )

    file_path = os.path.join(os.getcwd(), 'files', filename)
    try:
        blob = await file.read()
        with open(file_path, 'wb') as f:
            f.write(blob)
        code = await doc_to_pdf(file_path)
        if code:
            raise Exception

        await sleep(0.1)
        return FileResponse(f'./files/{name}.pdf', media_type='application/pdf')

    except Exception as e:
        with open(os.path.join(os.getcwd(), 'file_error.log'), 'w+', encoding='utf8') as file_error:
            file_error.writelines([e.__str__(), filename])

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=e.__str__() + filename
        )

@app.delete('/delete')
@app.post('/delete')
async def delete_files():
    for filename in os.listdir(os.path.join(os.getcwd(), 'files')):
        os.remove(os.path.join(os.getcwd(), 'files', filename))
    return {
        'code': 0,
        'message': 'success'
    }

@app.get('/log')
async def get_log():
    return FileResponse(os.path.join(os.getcwd(), 'error.log'))
